package cn.aj.basic.service.impl;

import cn.aj.basic.constant.EmailCodeConstant;
import cn.aj.basic.constant.SmsCodeConstant;
import cn.aj.basic.constant.WxSmsConstant;
import cn.aj.basic.exception.BussinessException;
import cn.aj.basic.service.IVerifyCodeImageService;
import cn.aj.basic.tdo.EmailCodeDto;
import cn.aj.basic.tdo.SmsCodeDto;
import cn.aj.basic.tdo.WxLoginSmsCodeDto;
import cn.aj.basic.utils.EmailUtil;
import cn.aj.basic.utils.StrUtils;
import cn.aj.basic.utils.VerifyCodeUtils;
import cn.aj.user.domain.User;
import cn.aj.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeImageServiceImpl implements IVerifyCodeImageService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
    * @Title: loadImg
    * @Description: TODO
    * @Author: Mr.GT
    * @Version: 1.0
    * @Date:  2022/11/24 0024 15:25
    * @Parameters: [imageCodeKey]
    * @Return java.lang.String
     * 图形验证码业务处理
    */
    @Override
    public String loadImg(String imageCodeKey) {
        //生成uuid
        String randomString = StrUtils.getComplexRandomString(1);
        // 存在redis,设置时间
        redisTemplate.opsForValue().set(imageCodeKey, randomString, 5, TimeUnit.MINUTES);
        // 转base64
        String base64Img = VerifyCodeUtils.VerifyCode(100, 50,randomString);
        return base64Img;
    }

    /**
    * @Title: getSmsCode
    * @Description: TODO
    * @Author: Mr.GT
    * @Version: 1.0
    * @Date:  2022/11/24 0024 15:25
    * @Parameters: [smsCodeDto]
    * @Return void
     * 手机短信验证码业务处理
    */
    @Override
    public void getSmsCode(SmsCodeDto smsCodeDto) {
        // 参数校验,注解完成
        // 图形验证码校验
        // 获取redis中图形验证码,先获取验证码的key
        String redisImgCode = (String) redisTemplate.opsForValue().get(smsCodeDto.getImageCodeKey());
        // 判断验证码是存在
        // 先判断redis中的图形验证码是否存在,然后再判断生成的图像验证码和redis中的验证码是否正确
        // 图形验证码比较区分大小写
        if(StringUtils.isBlank(redisImgCode) || !smsCodeDto.getImageCodeValue().equalsIgnoreCase(redisImgCode)) {
            throw new BussinessException("您输入的图形验证错误!");
        }
        // 手机短信2次验证码的时间内是否是60秒
        // redisTemplate.getExpire判断时间,单位秒
        Long ttl = redisTemplate.getExpire(String.format(SmsCodeConstant.PHONE_KEY, smsCodeDto.getPhone()));
        if (ttl != null && ttl > (SmsCodeConstant.PHONE_OVERDUE_TIME - 1) * 60) {
            throw new BussinessException("请您60秒再次获取!");
        }
        // 判断手机号是否注册过
        User user = userMapper.loadPhone(smsCodeDto.getPhone());
        if(user != null) {
            throw new BussinessException("您的手机号已经注册过!");
        }
        // 手机验证判断
        // 拿到redis中短信验证码
        String freshMsgCode="";
        String redisMsgCode = (String) redisTemplate.opsForValue().get(String.format(SmsCodeConstant.PHONE_KEY, smsCodeDto.getPhone()));
        if (StringUtils.isNoneBlank(redisMsgCode)) {
            // 验证码不存在,把redis中的赋值给它
            freshMsgCode=redisMsgCode;
        } else { // 重新生个验证码
            freshMsgCode = StrUtils.getRandomString(1);
        }
        log.info("手机验证码为{}", freshMsgCode);
        // 保存在redis中
        // 业务键加手机验证码,这是过期时间
        redisTemplate.opsForValue().set(String.format(SmsCodeConstant.PHONE_KEY, smsCodeDto.getPhone()), freshMsgCode, SmsCodeConstant.PHONE_OVERDUE_TIME, TimeUnit.MINUTES);

    }


    /**
    * @Title: loadEmail
    * @Description: TODO
    * @Author: Mr.GT
    * @Version: 1.0
    * @Date:  2022/11/24 0024 23:48
    * @Parameters: [emailCodeKey]
    * @Return java.lang.String
     * 邮箱图像验证码
    */
    @Override
    public String loadEmail(String emailCodeKey) {
        //生成uuid
        String randomString = StrUtils.getComplexRandomString(1);
        // 存在redis,设置时间
        redisTemplate.opsForValue().set(emailCodeKey, randomString, 5, TimeUnit.MINUTES);
        // 转base64
        String base64Email = VerifyCodeUtils.VerifyCode(100, 50,randomString);
        return base64Email;
    }

    /**
    * @Title: getEmailCode
    * @Description: TODO
    * @Author: Mr.GT
    * @Version: 1.0
    * @Date:  2022/11/25 0025 0:14
    * @Parameters: [emailCodeDto]
    * @Return void
     * 邮件业务判断
    */
    @Override
    public void getEmailCode(EmailCodeDto emailCodeDto) {
        // 参数非空校验
        // 先获取redis中的验证码,根据业务键可以去拿
        String redisEmailCode = (String) redisTemplate.opsForValue().get(emailCodeDto.getEmailCodeKey());
        if (StringUtils.isBlank(redisEmailCode) || !emailCodeDto.getEmailCodeValue().equalsIgnoreCase(redisEmailCode)) {
            throw new BussinessException("您输入的图形验证码不正确！");
        }
        // 判断两次邮件短信的间隔时间是否大于60
        Long expire = redisTemplate.getExpire(String.format(EmailCodeConstant.EMAIL_KEY, emailCodeDto.getEmail()));
        if(null != expire && expire > (EmailCodeConstant.EMAIL_OVERDUE_TIME - 1) * 60) {
            throw new BussinessException("请您60秒后再重新获取！");
        }
        // 判断邮箱是否被注册过
        User userEmail = userMapper.loadEmail(emailCodeDto.getEmail());
        if (userEmail != null) {
            throw new BussinessException("您的邮箱已经被注册过！");
        }

        // 先获取邮件
        String freshRedisEmail="";
        String redisEmail = (String) redisTemplate.opsForValue().get(String.format(EmailCodeConstant.EMAIL_KEY, emailCodeDto.getEmail()));
       if(StringUtils.isNoneBlank(freshRedisEmail)) {
           freshRedisEmail=redisEmail;
       } else {
           freshRedisEmail = StrUtils.getRandomString(1);
       }
        log.info("邮箱验证码为{}", freshRedisEmail);
        // 保存在redis中
        redisTemplate.opsForValue().set(String.format(EmailCodeConstant.EMAIL_KEY, emailCodeDto.getEmail()),freshRedisEmail,EmailCodeConstant.EMAIL_OVERDUE_TIME,TimeUnit.MINUTES);
        // 发邮件
        EmailUtil.sendEmail("邮箱注册" ,"982616996@qq.com", freshRedisEmail);
    }

    /**
    * @Title: getWxLoginSmsCode
    * @Description: TODO
    * @Author: Mr.GT
    * @Version: 1.0
    * @Date:  2022/11/27 0027 23:05
    * @Parameters: [wxLoginSmsCodeDto]
    * @Return void
     * 微信登录手机发手机短信
    */
    @Override
    public void getWxLoginSmsCode(WxLoginSmsCodeDto wxLoginSmsCodeDto) {
        // 手机短信2次验证码的时间内是否是60秒
        // redisTemplate.getExpire判断时间,单位秒
        Long wxSmsTtl = redisTemplate.getExpire(String.format(WxSmsConstant.WX_PHONE_KEY, wxLoginSmsCodeDto.getPhone()));
        if (wxSmsTtl != null && wxSmsTtl > (WxSmsConstant.WX_PHONE_OVERDUE_TIME - 1) * 60) {
            throw new BussinessException("请您60秒再次获取!");
        }
        // 判断手机号是否注册过
        User user = userMapper.loadPhone(wxLoginSmsCodeDto.getPhone());
        if(user != null) {
            throw new BussinessException("您的手机号已经注册过!");
        }
        // 手机验证判断
        // 拿到redis中短信验证码
        String freshWxMsgCode="";
        String redisWxMsgCode = (String) redisTemplate.opsForValue().get(String.format(WxSmsConstant.WX_PHONE_KEY, wxLoginSmsCodeDto.getPhone()));
        if (StringUtils.isNoneBlank(redisWxMsgCode)) {
            // 验证码不存在,把redis中的赋值给它
            freshWxMsgCode=redisWxMsgCode;
        } else { // 重新生个验证码
            freshWxMsgCode = StrUtils.getRandomString(1);
        }
        log.info("手机验证码为{}", freshWxMsgCode);
        // 保存在redis中
        // 业务键加手机验证码,这是过期时间
        redisTemplate.opsForValue().set(String.format(WxSmsConstant.WX_PHONE_KEY, wxLoginSmsCodeDto.getPhone()), freshWxMsgCode, WxSmsConstant.WX_PHONE_OVERDUE_TIME,TimeUnit.MINUTES);
    }
}
